package javase.ch02.sync;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Desc TODO
 * @Author chenmin
 * @Date 2025/10/30
 *
 * 三、Lock锁  悲观锁
 * java.util.concurrent.locks.Lock  接口
 * java.util.concurrent.locks.ReentrantLock  实现类  可重入锁  非公平锁
 *
 * 1.构造方法
 * public ReentrantLock()
 * public ReentrantLock(boolean fair)
 *
 * 2.常用API方法
 * public void lock()   获取锁
 * public void unlock() 释放锁,一定要在finally中完成释放锁的动作，无论是否发生异常一定会释放锁
 * public boolean tryLock()  尝试获取锁,返回true代表获取到锁，返回false则代表未获取锁
 * public boolean tryLock(long timeout, TimeUnit unit)  指定的时间内,尝试获取锁
 *
 * 3.注意
 * 必须在finally中释放锁资源，确保无论是否正常执行任务，都可以释放锁，从而避免因为出现异常而造成的死锁问题
 *
 *
 * 三、Lock锁  、 ReentrantLock 可重入锁
 *    1.语法   创建ReentrantLock对象  lock()获取锁   unlock()释放锁
 *
 *    2.作为属性
 *      2.1 private final ReentrantLock lock = new ReentrantLock();  成员属性
 *         - 使用同一个对象(s) 则lock锁也是同一个，此时会出现 “等待” 现象
 *         - 使用同两个对象(s1 、 s2) 则lock锁不是同一个，此时会出现 “争抢” 现象
 *
 *      2.2 private final static ReentrantLock lock = new ReentrantLock();  静态属性
 *         - 使用同一个对象(s) 则lock锁也是同一个，此时会出现 “等待” 现象
 *         - 使用同两个对象(s1 、 s2) 则lock锁是同一个，此时会出现 “等待”现象
 */
public class SyncTest3 {

    //创建一把锁
    private final static ReentrantLock lock = new ReentrantLock();


    public void m1(){
        //获取锁
        lock.lock();
        try{
            for (int i = 0; i < 5; i++) {
                System.out.println(Thread.currentThread().getName()+" i = "+i);
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }catch(Exception e){
            e.printStackTrace();
        }finally {
            //释放锁
            lock.unlock();
        }
    }


    public void m2(){
        //获取锁
        lock.lock();
        try{
            for (int i = 0; i < 5; i++) {
                System.out.println(Thread.currentThread().getName()+" i = "+i);
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }catch(Exception e){
            e.printStackTrace();
        }finally {
            //释放锁
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        SyncTest3 s1 = new SyncTest3();
        SyncTest3 s2 = new SyncTest3();

        //s对象是同一个,持有的lock锁是同一把锁
        //s1、s2对象不是同一个,持有的lock锁也不会是同一把锁
        new Thread(()->s1.m1(), "T1").start();
        new Thread(()->s2.m2(), "T2").start();
    }

}
